package com.shanzmoo.h5.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shanzmoo.core.service.IRedisSearchService;
import com.shanzmoo.core.util.RedisCoreKeyUtils;
import com.shanzmoo.db.picture.entity.MallBannerPictureEntity;
import com.shanzmoo.db.picture.service.IMallBannerPictureService;
import com.shanzmoo.db.product.entity.ProductCategoryEntity;
import com.shanzmoo.db.product.entity.dto.ProductCategoryDTO;
import com.shanzmoo.db.product.entity.dto.ProductSpuDto;
import com.shanzmoo.db.product.service.IProductCategoryService;
import com.shanzmoo.db.product.entity.dto.ProductSpuQueryDto;
import com.shanzmoo.db.product.entity.dto.SpuSearchDto;
import com.shanzmoo.h5.domain.vo.*;
import com.shanzmoo.core.service.IProductBaseRedisService;
import com.shanzmoo.h5.service.IProductRedisService;
import com.shanzmoo.base.bean.PageRespBase;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.constant.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 商品服务实现类
 *
 * @author： Gzhao 2020/12/27
 */
@Service
public class ProductRedisServiceImpl implements IProductRedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IProductBaseRedisService baseRedisService;
    @Autowired
    private IRedisSearchService redisSearchService;
    @Autowired
    private IMallBannerPictureService mallBannerPictureService;
    @Autowired
    private IProductCategoryService productCategoryService;

    @Override
    public List<String> getBannerList() {
        String key = RedisCoreKeyUtils.installBannerKey();

        List<String> result = stringRedisTemplate.opsForList().range(key, 0, -1);
        if (CollectionUtil.isNotEmpty(result)) {
            return result;
        }

        List<MallBannerPictureEntity> list = mallBannerPictureService.list(
                new QueryWrapper<MallBannerPictureEntity>()
                        .eq("deleted", false)
        );
        result = list.stream().map(MallBannerPictureEntity::getPictureUrl).collect(Collectors.toList());

        stringRedisTemplate.opsForList().leftPushAll(key, result);

        return result;
    }

    @Override
    public List<IndexCategoryVo> getIndexCategoryList() {
        String key = RedisCoreKeyUtils.installIndexCategoryKey();

        // 缓存数据行数
        Long size = stringRedisTemplate.opsForList().size(key);

        if (size == 0) {
            List<ProductCategoryEntity> firstCategoryList = productCategoryService.list(
                    new QueryWrapper<ProductCategoryEntity>()
                            .eq("deleted", false)
                            .eq("status", true)
                            .eq("shelves", true)
                            .eq("category_level", 1)
                            .orderByDesc("id")
            );
            List<String> reListStr = firstCategoryList.stream()
                    .map(e -> {
                        return JSON.toJSONString(IndexCategoryVo.create(e));
                    }).collect(Collectors.toList());

            size = Long.valueOf(reListStr.size());

            stringRedisTemplate.opsForList().leftPushAll(key, reListStr);
        }
        List<String> reListStr = stringRedisTemplate.opsForList().range(key, 0, -1);

        return reListStr.stream()
                .map(e -> JSON.parseObject(e, IndexCategoryVo.class))
                .collect(Collectors.toList());

    }

    @Override
    public PageRespBase<ProductSpuBriefVo> getRecommendList(Integer pageNum, Integer pageSize) {

        // 推荐商品
        String key = RedisCoreKeyUtils.installRecommendSpuKey();
        if (!stringRedisTemplate.hasKey(key)) {
            baseRedisService.updateAllRecommendSpu();
        }
        List<String> spuIds = stringRedisTemplate.opsForList().range(key, (long) (pageNum - 1) * pageSize,
                (long) pageNum * pageSize - 1);

        int totalSize = stringRedisTemplate.opsForList().size(key).intValue();

        // 商品销量
        final Map<String, Integer> spuSalesMap = baseRedisService.obatianSpuSalesMap(spuIds);

        List<ProductSpuBriefVo> resultList = baseRedisService.obtainAllSpu(spuIds).stream()
                .filter(e -> spuIds.contains(String.valueOf(e.getId())))
                .map(e -> {
                    return ProductSpuBriefVo.create(e, spuSalesMap.get(e.getId()));
                }).collect(Collectors.toList());

        return PageRespBase.create(totalSize, pageNum, pageSize, resultList);
    }

    @Override
    public SResponse<ProductSpuInfoVo> getInfo(String spu) {
        List<ProductSpuDto> allSpu = baseRedisService.obtainAllSpu(null);

        List<ProductSpuDto> tempList = allSpu.stream().filter(e -> e.getSpu().equals(spu)).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(tempList)) {
            return SResponse.fail(Constant.ERRCODE_LOGIC, "商品不存在");
        }
        ProductSpuDto baseSpu = tempList.get(0);

        String spuSalesKey = RedisCoreKeyUtils.installSpuSalesKey();
        Integer actualSales = (Integer) stringRedisTemplate.opsForHash().get(spuSalesKey, spuSalesKey);

        ProductSpuInfoVo productSpuInfoVo = ProductSpuInfoVo.builder()
                .spu(baseSpu.getSpu())
                .spuName(baseSpu.getName())
                .subheading(baseSpu.getSubheading())
                .freightPrice(baseSpu.getFreightPrice())
                .unit(baseSpu.getUnit())
                .describe(baseSpu.getDescribe())
                .salesCount(baseSpu.getBaseSales() + (actualSales == null ? 0 : actualSales))
                .pictureUrlList(baseRedisService.obtainTopPictureList(baseSpu.getId()))
                .pictureInfoUrlList(baseRedisService.obtainInfoPictureList(baseSpu.getId()))
                .skuList(baseRedisService.obtainSkuList(baseSpu.getId()))
                .attributeList(JSON.parseArray(baseSpu.getCheckAttr(), AttributeVo.class))
                .build();

        return SResponse.ok(productSpuInfoVo);
    }

    @Override
    public SResponse<List<MallCategoryVO>> getCategoryList(Integer categoryId) {
        List<ProductCategoryDTO> allCategoryList = baseRedisService.obtainAllCategory();

        // 二级分类
        List<MallCategoryVO> result = allCategoryList.stream()
                .filter(e ->
                        categoryId.equals(e.getParentId())
                ).map(e -> {
                    return MallCategoryVO.create(e);
                }).collect(Collectors.toList());

        // 三级分类
        result.forEach(mallCategoryVo -> {
            List<MallCategoryVO> children = allCategoryList.stream()
                    .filter(e ->
                            mallCategoryVo.getCategoryId().equals(e.getParentId())
                    ).map(e -> {
                        return MallCategoryVO.create(e);
                    }).collect(Collectors.toList());
            mallCategoryVo.setChildren(children);
        });
        return SResponse.ok(result);
    }

    @Override
    public PageRespBase<ProductSpuBriefVo> queryList(ProductSpuQueryDto query) {
        // 筛选商品名称
        List<String> spuSearchIds = null;
        if (StrUtil.isNotBlank(query.getSpuName())) {
            SResponse<List<SpuSearchDto>> searchResult = redisSearchService.query(query.getSpuName());

            if (!searchResult.isOk()) {
                return PageRespBase.create(0, query.getPageNum(), query.getPageSize(), Collections.EMPTY_LIST);
            } else {
                List<SpuSearchDto> searchList = searchResult.getData();
                spuSearchIds = searchList.stream().map(SpuSearchDto::getSpuId).collect(Collectors.toList());
            }
        }
        List<ProductSpuDto> spuList = baseRedisService.obtainAllSpu(spuSearchIds);

        // 筛选分类
        if (query.getCategoryId() != null) {
            spuList = spuList.stream()
                    .filter(e -> e.getCategoryId().equals(query.getCategoryId()))
                    .collect(Collectors.toList());
        }
        if (CollectionUtil.isEmpty(spuList)) {
            return PageRespBase.create(0, query.getPageNum(), query.getPageSize(), Collections.EMPTY_LIST);
        }

        // 商品销量
        List<String> spuIds = spuList.stream().map(ProductSpuDto::getId).collect(Collectors.toList());
        final Map<String, Integer> spuSalesMap = baseRedisService.obatianSpuSalesMap(spuIds);

        List<ProductSpuBriefVo> spuBriefVoList = spuList.stream()
                .map(e -> {
                    return ProductSpuBriefVo.create(e, spuSalesMap.get(e.getId()));
                }).collect(Collectors.toList());

        // 排序
        if (query.getSaleSort() != null) {
            Collections.sort(spuBriefVoList, Comparator.comparing(ProductSpuBriefVo::getSalesCount).reversed());
        }
        if (query.getPriceSort() != null) {
            if (query.getPriceSort()) {
                Collections.sort(spuBriefVoList, Comparator.comparing(ProductSpuBriefVo::getRetailPrice).reversed());
            } else {
                Collections.sort(spuBriefVoList, Comparator.comparing(ProductSpuBriefVo::getRetailPrice));
            }
        }

        // 取分页数据
        List<ProductSpuBriefVo> resultList = new ArrayList<>();

        int start = (query.getPageNum() - 1) * query.getPageSize();
        int end = query.getPageNum() * query.getPageSize();
        for (; start < end && start < spuBriefVoList.size(); start++) {
            resultList.add(spuBriefVoList.get(start));
        }

        return PageRespBase.create(spuBriefVoList.size(), query.getPageNum(), query.getPageSize(), resultList);
    }

}
